/*
	PlAr is Platform Arena: a 2D multiplayer shooting game
	Copyright (c) 2010, Antonio Ragagnin <spocchio@gmail.com>
    All rights reserved.

    This file is licensed under the New BSD License.
 */

package plar.ClientServer;

import java.awt.Point;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.DatagramPacket;

import java.net.SocketAddress;
import java.net.SocketException;
import java.util.Arrays;

public class Signal implements Serializable {
    static final long serialVersionUID = 1L;
    public static final byte NONE = 0;
    public static final byte MESSAGE = 1;
    public static final byte POINT = 2;
    public static final byte LOGIN = 3;
    public static final byte SPRITE = 4;
    public static final byte DIRECTION = 5;
    public static final byte INFO = 6;
    public static final byte SCREEN = 7;
    public static final byte INPUT = 8;
    public static final byte STOP = 9;
    public static final byte SPRITEANDSCREEN = 10;
    public static final byte LEVELINFO = 11;
    public static final byte WELCOME = 12;


    public static class Login implements Serializable {
        static final long serialVersionUID = 1L;
        public String userName;
        public String playerName;

    }

    public static class LevelInfo implements Serializable {
        static final long serialVersionUID = 1L;
        public String MOTD;
        public Point resolution;

        public float scaleX;
        public float scaleY;

    }

    public static class Info implements Serializable {
        static final long serialVersionUID = 1L;
        public float life;
        public int score;
        public String guns;
        public int spawns;
        public String chat;
		public long remaning;
        //	public ArrayList <String> players;
        public int currentgun=0;

    }

    public static class Input implements Serializable {
        static final long serialVersionUID = 1L;
        public int life;
        public String chat;
    }

    public static byte getID(byte[] data) {
        return data[0];
    }

    public static byte getKey(byte[] data) {
        return data[1];
    }

    public static byte getSignal(byte[] data) {
        return data[2];
    }

    public static byte[] setID(byte[] data, byte id) {
        data[0] = id;
        return data;
    }

    public static byte[] setKey(byte[] data, byte key) {
        data[1] = key;
        return data;
    }

    public static byte[] setSignal(byte[] data, byte key) {
        data[2] = key;
        return data;
    }

    public static byte[] concat(byte[] A, byte[] B) {
        byte[] C = new byte[A.length + B.length];
        System.arraycopy(A, 0, C, 0, A.length);
        System.arraycopy(B, 0, C, A.length, B.length);

        return C;
    }

    public static byte[] setBytes(byte[] data, byte id, byte key, byte signal) {

        byte[] info = { id, key, signal };
        // byte [] newData =new byte [data.length+3];
        return concat(info, data);

    }

    public static byte[] getData(byte[] data) {

        return Arrays.copyOfRange(data, 3, data.length);

    }

    public static DatagramPacket send(byte[] o, byte id, byte key, byte signal,
                                      SocketAddress addr) throws SocketException {
        // System.out.println("SENDING "+Arrays.copyOf(o, 10));
        // System.out.println("TO: "+addr.toString());
        byte[] data = setBytes(o, id, key, signal);
        DatagramPacket p = new DatagramPacket(data, 0, data.length, addr);
        // p.setAddress(addr);
        return p;
    }

    public static DatagramPacket send(Object o, byte id, byte key, byte signal,
                                      SocketAddress addr) throws SocketException {

        byte[] odata = toByteArray(o);
        byte[] data = setBytes(odata, id, key, signal);
        DatagramPacket p = new DatagramPacket(data, 0, data.length, addr);
        // p.setAddress(addr);
        return p;
    }

    public static byte[] toByteArray(Object obj) {
        byte[] bytes = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.flush();
            oos.close();
            bos.close();
            bytes = bos.toByteArray();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return bytes;
    }

    public static Object toObject(byte[] bytes) throws IOException,
        ClassNotFoundException {
        Object obj = null;
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bis);
        obj = ois.readObject();

        return obj;
    }

    public static byte[] from5IntTo6Bytes(int[] d) {
        byte[] b = new byte[6];
        b[0] = (byte) (d[0] & 0x000000FF);
        b[1] = (byte) ((d[0] & 0x00000300) >> 8);
        b[1] += (byte) ((d[1] & 0x0000003F) << 2);
        b[2] = (byte) ((d[1] & 0x000003C0) >> 6);
        b[2] += (byte) ((d[2] & 0x0000000F) << 4);
        b[3] = (byte) ((d[2] & 0x000003F0) >> 4);
        b[3] += (byte) ((d[3] & 0x00000003) << 6);
        b[4] = (byte) ((d[3] & 0x000003FC) >> 2);
        b[5] = (byte) d[4];
        return b;
    }
	public static byte From1ShortToFByte(short x)
{
	return (byte)((x & (0xFF00) ) >> 8);
}
	public static byte From1ShortToSByte(short x)
{
return (byte)((x & (0x00FF) ));
}

    public static short from2ByteTo1Short(byte y,byte x) {
						
        short z=0;
		z=(short)( (x & 0x00FF)  | ((y & 0x00FF) << 8));
        return z;
    }
    public static int[] from6ByteTo5Int(byte[] d) {
        int[] b = new int[5];
        b[0] = (int) ((d[0] & 0x000000FF) | ((d[1] & 0x00000003) << 8));
        b[1] = (int) ((d[1] & 0x000000FC) >> 2 | ((d[2] & 0x0000000F) << 6));
        b[2] = (int) ((d[2] & 0x000000F0) >> 4 | ((d[3] & 0x0000003F) << 4));
        b[3] = (int) ((d[3] & 0x000000C0) >> 6 | ((d[4] & 0x000000FF) << 2));

        // b[1] = ( ((int) (d[1] & 0xFC)) >>2) | ( ((int) (d[2] & 0x0F)) << 4);
        // b[2] = ( ((int) (d[2] & 0xF0)) >>4) | ( ((int) (d[3] & 0x3F)) << 4);
        // b[3] = ( ((int) (d[3] & 0xC0)) >>6) | ( ((int) (d[4] & 0xFF)) << 4);
        b[4] = (int) (d[5] & 0x000000FF);

        return b;
    }
}
